package com.vgooo.client.ui;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ListView;

/** 
 * <p>一个可以监听ListView是否滚动到最顶部或最底部的自定义控件</p> 
 * 只能监听由触摸产生的，如果是ListView本身Flying导致的，则不能监听</br> 
 * 如果加以改进，可以实现监听scroll滚动的具体位置等 
 */
  
public class ScrollOverListView extends ListView { 
  
    private int mLastY; 
    private int mTopPosition; 
    private int mBottomPosition; 
  
    public ScrollOverListView(Context context, AttributeSet attrs, int defStyle) { 
        super(context, attrs, defStyle); 
        init(); 
    } 
  
    public ScrollOverListView(Context context, AttributeSet attrs) { 
        super(context, attrs); 
        init(); 
    } 
  
    public ScrollOverListView(Context context) { 
        super(context); 
        init(); 
    } 
  
//	@Override
//	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//		// TODO Auto-generated method stub
//		int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >>2, MeasureSpec.AT_MOST);
//		super.onMeasure(widthMeasureSpec, expandSpec);
//	}
    
    private void init(){ 
        mTopPosition = 0; 
        mBottomPosition = 0; 
    } 
  
    @Override
    public boolean onTouchEvent(MotionEvent ev) { 
        final int action = ev.getAction(); 
        final int y = (int) ev.getRawY(); 
  
        switch(action){ 
            case MotionEvent.ACTION_DOWN:{ 
                mLastY = y; 
                final boolean isHandled = mOnScrollOverListener.onMotionDown(ev); 
                if (isHandled) { 
                    mLastY = y; 
                    return isHandled; 
                } 
                break; 
            } 
  
            case MotionEvent.ACTION_MOVE:{ 
                final int childCount = getChildCount(); 
                if(childCount == 0) return super.onTouchEvent(ev); 
  
                final int itemCount = getAdapter().getCount() - mBottomPosition; 
  
                final int deltaY = y - mLastY; 
                //DLog.d("lastY=%d y=%d", mLastY, y); 
  
                final int firstTop = getChildAt(0).getTop(); 
                final int listPadding = getListPaddingTop(); 
  
                final int lastBottom = getChildAt(childCount - 1).getBottom(); 
                final int end = getHeight() - getPaddingBottom(); 
  
                final int firstVisiblePosition = getFirstVisiblePosition(); 
  
                final boolean isHandleMotionMove = mOnScrollOverListener.onMotionMove(ev, deltaY); 
  
                if(isHandleMotionMove){ 
                    mLastY = y; 
                    return true; 
                } 
  
                //DLog.d("firstVisiblePosition=%d firstTop=%d listPaddingTop=%d deltaY=%d", firstVisiblePosition, firstTop, listPadding, deltaY); 
                if (firstVisiblePosition <= mTopPosition && firstTop >= listPadding && deltaY > 0) { 
                    final boolean isHandleOnListViewTopAndPullDown; 
                    isHandleOnListViewTopAndPullDown = mOnScrollOverListener.onListViewTopAndPullDown(deltaY); 
                    if(isHandleOnListViewTopAndPullDown){ 
                        mLastY = y; 
                        return true; 
                    } 
                } 
  
                // DLog.d("lastBottom=%d end=%d deltaY=%d", lastBottom, end, deltaY); 
                if (firstVisiblePosition + childCount >= itemCount && lastBottom <= end && deltaY < 0) { 
                    final boolean isHandleOnListViewBottomAndPullDown; 
                    isHandleOnListViewBottomAndPullDown = mOnScrollOverListener.onListViewBottomAndPullUp(deltaY); 
                    if(isHandleOnListViewBottomAndPullDown){ 
                        mLastY = y; 
                        return true; 
                    } 
                } 
                break; 
            } 
  
            case MotionEvent.ACTION_UP:{ 
                final boolean isHandlerMotionUp = mOnScrollOverListener.onMotionUp(ev); 
                if (isHandlerMotionUp) { 
                    mLastY = y; 
                    return true; 
                } 
                break; 
            } 
        } 
  
        mLastY = y; 
        return super.onTouchEvent(ev); 
    } 
  
    /**空的*/
    private OnScrollOverListener mOnScrollOverListener = new OnScrollOverListener(){ 
  
        @Override
        public boolean onListViewTopAndPullDown(int delta) { 
            return false; 
        } 
  
        @Override
        public boolean onListViewBottomAndPullUp(int delta) { 
            return false; 
        } 
  
        @Override
        public boolean onMotionDown(MotionEvent ev) { 
            return false; 
        } 
  
        @Override
        public boolean onMotionMove(MotionEvent ev, int delta) { 
            return false; 
        } 
  
        @Override
        public boolean onMotionUp(MotionEvent ev) { 
            return false; 
        } 
  
    }; 
  
    // =============================== public method =============================== 
  
    /** 
     * 可以自定义其中一个条目为头部，头部触发的事件将以这个为准，默认为第一个 
     * 
     * @param index 正数第几个，必须在条目数范围之内 
     */
    public void setTopPosition(int index){ 
        if(getAdapter() == null) 
            throw new NullPointerException("You must set adapter before setTopPosition!"); 
        if(index < 0) 
            throw new IllegalArgumentException("Top position must > 0"); 
  
        mTopPosition = index; 
    } 
  
    /** 
     * 可以自定义其中一个条目为尾部，尾部触发的事件将以这个为准，默认为最后一个 
     * 
     * @param index 倒数第几个，必须在条目数范围之内 
     */
    public void setBottomPosition(int index){ 
        if(getAdapter() == null) 
            throw new NullPointerException("You must set adapter before setBottonPosition!"); 
        if(index < 0) 
            throw new IllegalArgumentException("Bottom position must > 0"); 
  
        mBottomPosition = index; 
    } 
  
    /** 
     * 设置这个Listener可以监听是否到达顶端，或者是否到达低端等事件</br> 
     * 
     * @see OnScrollOverListener 
     */
    public void setOnScrollOverListener(OnScrollOverListener onScrollOverListener){ 
        mOnScrollOverListener = onScrollOverListener; 
    } 
  
    /** 
     * 滚动监听接口</br> 
     * @see ScrollOverListView#setOnScrollOverListener(OnScrollOverListener) 
     * 
     */
    public interface OnScrollOverListener { 
  
        /** 
         * 到达最顶部触发 
         * 
         * @param delta 手指点击移动产生的偏移量 
         * @return 
         */
        boolean onListViewTopAndPullDown(int delta); 
  
        /** 
         * 到达最底部触发 
         * 
         * @param delta 手指点击移动产生的偏移量 
         * @return 
         */
        boolean onListViewBottomAndPullUp(int delta); 
  
        /** 
         * 手指触摸按下触发，相当于{@link MotionEvent#ACTION_DOWN} 
         * 
         * @return 返回true表示自己处理 
         * @see View#onTouchEvent(MotionEvent) 
         */
        boolean onMotionDown(MotionEvent ev); 
  
        /** 
         * 手指触摸移动触发，相当于{@link MotionEvent#ACTION_MOVE} 
         * 
         * @return 返回true表示自己处理 
         * @see View#onTouchEvent(MotionEvent) 
         */
        boolean onMotionMove(MotionEvent ev, int delta); 
  
        /** 
         * 手指触摸后提起触发，相当于{@link MotionEvent#ACTION_UP} 
         * 
         * @return 返回true表示自己处理 
         * @see View#onTouchEvent(MotionEvent) 
         */
        boolean onMotionUp(MotionEvent ev); 
  
    } 
  
}
